//
// Created by LONG on 2020/11/8.
//

#include "l1Dl.h"

void RAN_L1_DL_SendEndMsgToUe(S_RanL1CellInst *pCellInst)
{
    int32_t rc;
    S_RanCommMsgHdr commMsgHdr;

    commMsgHdr.type = RAN_L1_API_MSG_BUTT;
    commMsgHdr.size = sizeof(commMsgHdr);
    VRB_PUT(rc, pCellInst->pRanUeQue, &commMsgHdr, sizeof(commMsgHdr));
//    CSP_LOG_INF(RAN_MD_L1_DL, "RAN_L1_DL_SendEndMsgToUe() commMsgHdr.type = %#x\n", commMsgHdr.type);
}

void RAN_L1_DL_SendDataToUe(S_RanL1CellInst *pCellInst)
{
    int32_t rc;
    uint32_t size;
    uint32_t sfnSlot;
    void *msgBuffer;
    S_VarRingBuffer *pDlTtiBuff;

    O5G_SfnSlot_ToU32(pCellInst->sfn, pCellInst->slot, pCellInst->slotNum, &sfnSlot);
    pDlTtiBuff = pCellInst->pDlTtiBuff[sfnSlot % RAN_L1_TTI_BUFF_NUM];

    while (1)
    {
        msgBuffer = VarRB_ReadRequest(pDlTtiBuff, &size);
        IF_BREAK(==, NULL, msgBuffer, NO_LOG_MESSAGE);
        VRB_PUT(rc, pCellInst->pRanUeQue, msgBuffer, size);
        VarRB_ReadConsume(pDlTtiBuff, msgBuffer);
    }
    RAN_L1_DL_SendEndMsgToUe(pCellInst);
}

void RAN_L1_DL_CellProcess(S_RanL1CellInst *pCellInst)
{
    int32_t rc;
    uint32_t size;
    S_RanCommMsgHdr *pCommMsgHdr;

    while (1)
    {
        pCommMsgHdr = VarRB_ReadRequest(pCellInst->pL2L1UpMsgQue, &size);
        IF_BREAK(==, NULL, pCommMsgHdr, NO_LOG_MESSAGE);

        switch (pCommMsgHdr->type)
        {
        case RAN_L1_API_MSG_DL_TTI_REQ:
        {
            uint32_t sfnSlot;
            S_RanL1ApiMsgDlTtiReq *pDlTtiReq;

            pDlTtiReq = (S_RanL1ApiMsgDlTtiReq *)pCommMsgHdr;

            pCellInst->recvTtiReqCount++;

            O5G_SfnSlot_ToU32(pDlTtiReq->sfn, pDlTtiReq->slot, pCellInst->slotNum, &sfnSlot);

            VRB_PUT(rc, pCellInst->pDlTtiBuff[sfnSlot % RAN_L1_TTI_BUFF_NUM], pCommMsgHdr, size);

//            CSP_LOG_INF(RAN_MD_L1_DL, "RAN_L1_DL_CellProcess() recv RAN_L1_API_MSG_DL_TTI_REQ. %u [%u, %u] [%u, %u]\n",
//                sfnSlot, pCellInst->sfn, pCellInst->slot, pDlTtiReq->sfn, pDlTtiReq->slot);
        }
            break;
        default:
            CSP_LOG_WRN(RAN_MD_L1_DL, "RAN_L1_CellCpProcess() recv unsupport msg[%#x]\n", pCommMsgHdr->type);
            break;
        }
        VarRB_ReadConsume(pCellInst->pL2L1UpMsgQue, pCommMsgHdr);
    }
}

void RAN_L1_DL_NodeBProcess(S_RanL1NbInst *pNbInst)
{
    uint32_t count;
    uint32_t cellLoop;
    S_RanL1CellInst *pCellInst;

    for (cellLoop = 0; cellLoop < RAN_CELL_NUM_MAX; cellLoop++)
    {
        pCellInst = &pNbInst->cellInst[cellLoop];
        IF_CONTINUE(==, FALSE, pCellInst->inUse, NO_LOG_MESSAGE);

        RAN_L1_DL_CellProcess(pCellInst);

        count = 0;
        while (pCellInst->sendTtiIntCount != pCellInst->recvTtiReqCount)
        {
            RAN_L1_DL_CellProcess(pCellInst);
            usleep(1000);
            if (count++ > 10000)
            {
                assert(0);
            }
        }
        RAN_L1_DL_SendDataToUe(pCellInst);
    }
}

void RAN_L1_DL_RanProcess()
{
    uint32_t nbLoop;
    S_RanL1NbInst *pNbInst;

    for (nbLoop = 0; nbLoop < RAN_NODEB_NUM_MAX; nbLoop++)
    {
        pNbInst = &gpRanL1Context->nbInst[nbLoop];
        IF_CONTINUE(==, FALSE, pNbInst->inUse, NO_LOG_MESSAGE);
        RAN_L1_DL_NodeBProcess(pNbInst);
    }
}

void RAN_L1_DL_Process(void)
{
    RAN_L1_DL_RanProcess();
}
